package com.example.myspringframework.beans.factory;

import com.example.myspringframework.beans.BeansException;
import com.example.myspringframework.beans.PropertyValue;
import com.example.myspringframework.beans.PropertyValues;
import com.example.myspringframework.beans.factory.config.BeanDefinition;
import com.example.myspringframework.beans.factory.config.BeanFactoryPostProcessor;
import com.example.myspringframework.core.io.DefaultResourceLoader;
import com.example.myspringframework.core.io.Resource;
import com.example.myspringframework.utils.StringValueResolver;

import java.io.IOException;
import java.util.Properties;

/**
 * 解析属性占位符
 */
public class PropertyPlaceholderConfigurer  implements BeanFactoryPostProcessor {
    private String location;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 加载属性配置文件
        Properties properties = loadProperties();
        // 填充属性值
        processProperties(beanFactory, properties);

        //往容器中添加字符解析器，供解析@Value注解使用
        StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(properties);
        beanFactory.addEmbeddedValueResolver(valueResolver);
    }

    // 填充属性值
    private void processProperties(ConfigurableListableBeanFactory beanFactory, Properties properties) {
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName);
            resolvePropertyValues(beanDefinition, properties);
        }
    }

    private void resolvePropertyValues(BeanDefinition beanDefinition, Properties properties) {
        PropertyValues propertyValues = beanDefinition.getPropertyValues();
        for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
            Object value = propertyValue.getValue();
            if (value instanceof String str) {
                String val = this.resolvePlaceholder(str, properties);
                propertyValues.addPropertyValue(new PropertyValue(propertyValue.getName(),val));
            }
        }
    }

    private String resolvePlaceholder(String value, Properties properties) {
        //TODO 仅简单支持一个占位符的格式
        StringBuilder buf = new StringBuilder(value);
        int startIndex = value.indexOf("${");
        int endIndex = value.indexOf("}");
        if (startIndex != -1 && endIndex != -1 && startIndex < endIndex) {
            String propKey = value.substring(startIndex + 2, endIndex);
            String propVal = properties.getProperty(propKey);
            buf.replace(startIndex, endIndex + 1, propVal);
        }
        return buf.toString();
    }

    // 加载Properties文件
    private Properties loadProperties() {
        DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
        Resource resource = resourceLoader.getResource(this.location);
        Properties props = new Properties();
        try {
            props.load(resource.getInputStream());
            return props;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void setLocation(String location) {
        this.location = location;
    }

    private class PlaceholderResolvingStringValueResolver implements StringValueResolver {
        private final Properties properties;

        public PlaceholderResolvingStringValueResolver(Properties properties) {
            this.properties = properties;
        }

        @Override
        public String resolveStringValue(String strVal) {
            return resolvePlaceholder(strVal, this.properties);
        }
    }
}

